D) Expression Template

Expression Template
Expression template are a C++ template meta-programming technique that builds
structures representing a computation at compile time, where expressions are evaluated only
as needed to produce efficient code for the entire computation.
Expression template thus allow programmers to bypass the normal order of evaluation of the
C++ language and achive optimizations such as loop fusion
Native Approach
#include <iostream>
#include <vector>
template <typename T>
class MyVector{
private:
std::vector<T> cont;
public:
MyVector(const std::size_t n): cont(n) {}
MyVector(const std::size_t n, const double initialValue): cont(n, initialValue) {}
std::size_t size(void) const {
return cont.size();
}
T operator[](const std::size_t i) const {
return cont[i];
}
T& operator[](const std::size_t i){
return cont[i];
}
};
// function template for +
template <typename T>
MyVector<T> operator+(const MyVector<T>& a, const MyVector<T>& b){
MyVector<T> result(a.size());
for(std::size_t s=0; s<=a.size(); ++s){
result[s]=a[s]+b[s];
}
return result;
}
// function template for *
template <typename T>
MyVector<T> operator*(const MyVector<T>& a, const MyVector<T>& b){
MyVector<T> result(a.size());
for(std::size_t s=0; s<=a.size(); ++s){
result[s]=a[s]*b[s];
}
return result;
}
// function template for <<
template <typename T>
std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){
std::cout<<std::endl;
for(int i=0; i<cont.size(); ++i){
os<<cont[i]<<' ';
}
os<<std::endl;
return os;
}
int main(void){
MyVector<double> x(10, 5.4);
MyVector<double> y(10, 10.3);
MyVector<double> result(10);
result=x+x+y*y;
std::cout<<result<<std::endl;
return 0;
}

116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 

Temporaries
위와 같이 모든 연산자에 대하여서 정의해 주고 연산을 할 경우,
임시 변수 사용량이 증가하게 된다.

Instead of performing the vector operations greddy, Create the expression tree
for result[i] at compile time in a lazy manner.
Expression Template
ExpressionTree
#include <cassert>
#include <iostream>
#include <vector>
template <typename T, typename Cont=std::vector<T>>
class MyVector{
private:
Cont cont;
public:
MyVector(const std::size_t n): cont(n) {}
MyVector(const std::size_t n, const double initialValue): cont(n, initialValue) {}
MyVector(const Cont& other): cont(other) {}
template <typename T2, typename R2>
MyVector& operator=(const MyVector<T2, R2>& other){
assert(size()==other.size());
for(std::size_t i=0; i<cont.size(); ++i) cont[i]=other[i];
return *this;
}
std::size_t size(void) const {
return cont.size();
}
T operator[](const std::size_t i) const {
return cont[i];
}
T& operator[](const std::size_t i){
return cont[i];
}
const Cont& data(void) const {
return cont;
}
Cont& data(void){
return cont;
}
};
// MyVector+MyVector
template <typename T, typename Op1, typename Op2>
class MyVectorAdd{
private:
const Op1& op1;
const Op2& op2;
public:
MyVectorAdd(const Op1& a, const Op2& b): op1(a), op2(b) {}
T operator[](const std::size_t i) const {
return op1[i]+op2[i];
}
std::size_t size(void) const {
return op1.size();
}
};
// MyVector*MyVector
template <typename T, typename Op1, typename Op2>
class MyVectorMul{
private:
const Op1& op1;
const Op2& op2;
public:
MyVectorMul(const Op1& a, const Op2& b): op1(a), op2(b) {}
T operator[](const std::size_t i) const {
return op1[i]*op2[i];
}
std::size_t size(void) const {
return op1.size();
}
};
// function tempalte for the + operator
template <typename T, typename R1, typename R2>
MyVector<T, MyVectorAdd<T, R1, R2>> operator+(const MyVector<T, R1>& a, const MyVector<T, R2>& b){
return MyVector<T, MyVectorAdd<T, R1, R2>>(MyVectorAdd<T, R1, R2>(a.data(), b.data()));
}
// function tempalte for the * operator
template <typename T, typename R1, typename R2>
MyVector<T, MyVectorMul<T, R1, R2>> operator*(const MyVector<T, R1>& a, const MyVector<T, R2>& b){
return MyVector<T, MyVectorMul<T, R1, R2>>(MyVectorMul<T, R1, R2>(a.data(), b.data()));
}
// function tempalte for the << operator
template <typename T>
std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){
std::cout<<std::endl;
for(int i=0; i<cont.size(); ++i){
os<<cont[i]<<' ';
}
os<<std::endl;
return os;
}
int main(void){
MyVector<double> x(10, 5.4);
MyVector<double> y(10, 10.3);
MyVector<double> result(10);
result=x+x+y*y;
std::cout<<result<<std::endl;
return 0;
}

116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89

Exression